package owlapps2012.owlToSql.events.p4;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;

import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import org.apache.log4j.Logger;
import org.coode.owlapi.manchesterowlsyntax.ManchesterOWLSyntaxEditorParser;
import org.protege.editor.owl.model.inference.OWLReasonerManager;
import org.protege.editor.owl.model.inference.ReasonerStatus;
import org.protege.editor.owl.model.inference.ReasonerUtilities;
import org.protege.editor.owl.ui.action.ProtegeOWLAction;
import org.protege.editor.owl.ui.renderer.EventRendering;
import org.semanticweb.owlapi.expression.ParserException;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyRenameException;
import org.semanticweb.owlapi.reasoner.InferenceType;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.util.SimpleShortFormProvider;

import owlapps2012.base.DLQueryParser;
import owlapps2012.owlToSql.base.CompoundCategoryTransformer;
import owlapps2012.owlToSql.base.DynamicDbAppConfig;
import owlapps2012.owlToSql.base.OwlToSqlTransformationException;
import owlapps2012.owlToSql.base.TemporalExpressionAnalyzer;
import owlapps2012.owlToSql.base.TextProcessingUtils;
import owlapps2012.owlToSql.events.EventsTransformer;
import uk.ac.manchester.cs.owl.owlapi.mansyntaxrenderer.ManchesterOWLSyntaxOWLObjectRendererImpl;

/**
* Author: Piotr Nowara<br>
* piotrnowara@gmail.com<br>
* code made available under Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.html)<br>
* copyright 2013, Piotr Nowara<br>
*/
public class LinkedFactsCategoryExport extends ProtegeOWLAction
{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -2223265784686633224L;
	private static final String configFileName = "EventsToSQLP4Transformer.properties";
	private static final String dbConfigFileName = "LinkedFactsP4DbConfig.properties";
	private static final String DB_VERSION_CHCECKING = "CategoryVersionChecking";
//	private static final String reportFileSeparator = "^\t";
	private static Logger log = Logger.getLogger(LinkedFactsCategoryExport.class);
	private String jarDirectory;
	private DynamicDbAppConfig lfConfig;
	private OWLAnnotationProperty sqlSelectAP;
	private OWLAnnotationProperty backwardValidityAP;
	private OWLAnnotationProperty forwardValidityAP;
	private OWLAnnotationProperty baseCategoryAP;
	private OWLReasoner reasoner;
	private OWLOntology activeOntology;
	private EventsTransformer temporalCategoryTransformer;
	private CompoundCategoryTransformer compoundCategoryTransformer;
	private ArrayList<OWLClass> listOfSuccesfullyTransformedCategories = new ArrayList<OWLClass>();
	private ArrayList<OWLClass> listOfNotTransformedCategories = new ArrayList<OWLClass>();
	private LinkedFactsCategoryExportDbTools dbTools;
	private ManchesterOWLSyntaxOWLObjectRendererImpl renderer;
	private HashSet<String> alreadyCheckedCombinations;
	private boolean versionChceckingMode;
	private DLQueryParser dlQueryParser;



	@Override
	public void initialise() throws Exception 
	{
		this.jarDirectory = new File(LinkedFactsCategoryExport.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath();
		try 
		{
			this.lfConfig = new DynamicDbAppConfig(this.jarDirectory.concat(File.separator).concat(configFileName), this.jarDirectory.concat(File.separator).concat(dbConfigFileName));
		} 
		catch (Exception e) 
		{
			throw new Exception("Unable to read configuration file!", e);
		}
		this.temporalCategoryTransformer = new EventsTransformer(this.lfConfig);
		this.compoundCategoryTransformer = new CompoundCategoryTransformer(this.lfConfig);
		
		this.renderer = new ManchesterOWLSyntaxOWLObjectRendererImpl();
		this.versionChceckingMode = this.lfConfig.getDbConfig().getProperty(DB_VERSION_CHCECKING, "N").equals("Y");

		
//		this.initDbConnection();
	}
	
    private void initDbConnection() throws Exception 
    {
		Connection conn = null;
		String[] dbSignOnData = showDatabeseSignOnPanel(this.lfConfig.getDbUserName());
   		String dbUser = dbSignOnData[0];
   		String dbPasswd = dbSignOnData[1];
		
		if(dbPasswd != null)
	        try 
			{
	        	conn = getUserProvidedConnection(this.lfConfig.getDbConnURL(), this.lfConfig.getDbDriverName(), dbUser, dbPasswd);
//	        	conn.setAutoCommit(true);
	        	conn.setAutoCommit(false);
//				this.dbTools.setDbConnection(getUserProvidedConnection(this.lfConfig.getDbConnURL(), this.lfConfig.getDbDriverName(), this.lfConfig.getDbUserName(), dbPasswd));
			} 
	        catch (Exception e)
			{
				JOptionPane.showMessageDialog(this.getOWLWorkspace(),
		                "Error while attempting to establish a database connection: "+e.getMessage(),
		                "Error Message",
		                JOptionPane.ERROR_MESSAGE);
				this.initDbConnection();
			}
		
    	if(this.lfConfig.getSqlType() == null)
			throw new Exception("No SQL type specified!");
		if(this.lfConfig.getSqlType().getName().equals("DB2"))
			this.dbTools = new LinkedFactsCategoryExportDB2Tools(conn);
		else
			throw new Exception("Additional configuration needed for "+this.lfConfig.getSqlType().getName());
		

	}


	@Override
	public void dispose() throws Exception {
		// TODO Auto-generated method stub
	}

	@Override
	public void actionPerformed(ActionEvent e)
	{
		try 
		{
			this.initOWLObjects();
		} 
		catch (Exception owlE) 
		{
			log.error(owlE);
			return;
		}
		
        OWLClass lastSelectedClass = getOWLWorkspace().getOWLSelectionModel().getLastSelectedClass();
		try 
		{
			if(dbTools == null)
				initDbConnection();
			
			if(e.getActionCommand().equals("Linked Facts - export selected category"))
			{
				if(!dbTools.dbChceckIfCategoryAlreadyExported(lastSelectedClass))
				{
					this.listOfSuccesfullyTransformedCategories.clear();
					this.exportCategory(lastSelectedClass);
//					if(versionChceckingMode)
//        		    	this.exportNewVersionsOfRelatedCategories();
				}
				else
				{
					log.info("Category already exported.");
					JOptionPane.showMessageDialog(this.getOWLWorkspace(),
							"Category already exported.",
							e.getActionCommand(),
							JOptionPane.INFORMATION_MESSAGE);
					return;
				}
					
			}
			else if(e.getActionCommand().equals("Linked Facts - export hierarchy"))//export all inferred subclasses (without the selected class) 
			{
				this.listOfSuccesfullyTransformedCategories.clear();
				Set<OWLClass> classesToTranslate = reasoner.getSubClasses(lastSelectedClass, false).getFlattened();
//			    classesToTranslate.add(lastSelectedClass);
			    for (OWLClass classToTranslate : classesToTranslate) 
			    {
			    	if(!classToTranslate.isOWLNothing())
			    	{
			    		if(dbTools.dbChceckIfCategoryAlreadyExported(classToTranslate))
			    			log.info("Category already exported: "+renderer.render(classToTranslate));
			    		else 
			    			this.exportCategory(classToTranslate);
			    	}
			    }
//			    if(versionChceckingMode)
//    		    	this.exportNewVersionsOfRelatedCategories();
			}
			
			try 
			{
				dbTools.dbCommit();
			} 
			catch (SQLException e2)
			{
				e2.printStackTrace();
				log.error(e2);
			}
			
			JOptionPane.showMessageDialog(this.getOWLWorkspace(),
	                "Export succesful - check log for details.",
	                e.getActionCommand(),
	                JOptionPane.INFORMATION_MESSAGE);
		}
		catch (Exception e1) 
		{
			e1.printStackTrace();
			log.error(e);
			if(dbTools != null)
				try 
				{
					dbTools.dbRollback();
				} 
				catch (SQLException e2)
				{
					e2.printStackTrace();
					log.error(e2);
				}
			JOptionPane.showMessageDialog(this.getOWLWorkspace(),
	                "Error while attempting to export a category: "+e1.getMessage(),
	                e.getActionCommand(),
	                JOptionPane.ERROR_MESSAGE);
			return;
		} 
		
		if(lfConfig.isWriteReport())
			this.writeReport();
//		this.generateSQLExpression();
	}
	
	private Long exportNewCategory(OWLClass categoryToExport) throws OwlToSqlTransformationException
	{
		listOfSuccesfullyTransformedCategories.clear();
		return exportCategory(categoryToExport);
	}

	private void exportNewVersionsOfRelatedCategories() throws SQLException, OwlToSqlTransformationException, OWLOntologyRenameException, ParserException 
	{
		ArrayList<OWLClass> listOfCategoriesToCheck = new ArrayList<OWLClass>(listOfSuccesfullyTransformedCategories);
		ArrayList<String> listOfDependentCategories = new ArrayList<String>();
		log.info("listOfSuccesfullyTransformedCategories: "+listOfCategoriesToCheck);
		log.info(listOfSuccesfullyTransformedCategories.size());
		log.info("listOfCategoriesToCheck: "+listOfCategoriesToCheck);
		log.info(listOfCategoriesToCheck.size());
		for(int i=0;i<listOfCategoriesToCheck.size();i++)
		{
			OWLClass cat = listOfCategoriesToCheck.get(i);
			String catName = cat.getIRI().getFragment();
			if(!catName.contains("__v"))
				throw new OwlToSqlTransformationException("Category without version: "+catName);
			String versionInfo = catName.substring(catName.lastIndexOf("__v")+2);
			String catNameWithoutVersion = catName.substring(0,catName.lastIndexOf("__v"));
			int newVersion;
			if(versionInfo.matches("v[0-9]{1,}"))
				newVersion = Integer.parseInt(versionInfo.substring(1));
			else
				continue;
			if(newVersion < dbTools.dbGetLastVersion(cat))
				throw new OwlToSqlTransformationException("Attempt to export outdated version of category: "+cat);
			int oldVersion = newVersion-1;
			String catNamePreviousVersion = catNameWithoutVersion+"__v"+oldVersion;
			if(newVersion > 1)
				listOfDependentCategories.addAll(this.deleteOldVersionsOfTheSameCategory(this.getDependencies(activeOntology.getOntologyID().getOntologyIRI()+"#"+catNamePreviousVersion)));
			
			log.info("listOfDependentCategories:"+listOfDependentCategories);
			for(String depCatName : listOfDependentCategories)
			{
//				OWLClass dependentOWLClass = getOWLDataFactory().getOWLClass(IRI.create(activeOntology.getOntologyID().getOntologyIRI()+"#"+depCatName));
				OWLClass dependentOWLClass;
//				String[] s = depCatName.split("__v");
//				log.info("depCatName:"+depCatName);
				String depCatNameWihoutVersion = depCatName.substring(0, depCatName.lastIndexOf("__v"));
				int version = Integer.parseInt(depCatName.substring(depCatName.lastIndexOf("__v")+3));
				OWLClass newDependentOWLClass;
				int c = 0;
				do
				{
					String depCatCurrentName = depCatNameWihoutVersion + "__v" + (version + c);
					dependentOWLClass = getOWLDataFactory().getOWLClass(IRI.create(activeOntology.getOntologyID().getOntologyIRI()+"#"+depCatCurrentName));
					c++;
					String depCatNewName = depCatNameWihoutVersion + "__v" + (version + c);
					newDependentOWLClass = getOWLDataFactory().getOWLClass(IRI.create(activeOntology.getOntologyID().getOntologyIRI()+"#"+depCatNewName));
					
				}
				while(dbTools.dbChceckIfCategoryAlreadyExported(newDependentOWLClass));
				String newDef = getCategoryAxiom(dependentOWLClass).replaceAll(catNamePreviousVersion, catName);
				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLEquivalentClassesAxiom(newDependentOWLClass, dlQueryParser.parseClassExpression(newDef))));
				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLSubClassOfAxiom(newDependentOWLClass, dlQueryParser.parseClassExpression(newDef.split(" ")[0]))));
	    		activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(newDependentOWLClass.getIRI(), getOWLDataFactory().getOWLAnnotation(getOWLDataFactory().getRDFSComment(), getOWLDataFactory().getOWLLiteral("This version was created autmatically on "+new java.util.Date()+".")))));
	    		exportNewCategory(newDependentOWLClass);
			}
			
		}
		
	}
	
	private ArrayList<String> deleteOldVersionsOfTheSameCategory(ArrayList<String> dependencies) throws OwlToSqlTransformationException 
	{
		HashMap<String, Integer> highestVersions = new HashMap<String, Integer>();
		for (String cat : dependencies)
		{
			if(!cat.contains("__v"))
				throw new OwlToSqlTransformationException("Category without version: "+cat);
			String catName = cat.substring(0, cat.lastIndexOf("__v"));
			int catVer = Integer.parseInt(cat.substring(cat.lastIndexOf("__v")+3));
			if(!highestVersions.containsKey(catName))
				highestVersions.put(catName, Integer.valueOf(catVer));
			else
			{
				int version = highestVersions.get(catName);
				if(version < catVer)
				{
					highestVersions.remove(catName);
					highestVersions.put(catName, Integer.valueOf(catVer));
				}
			}
		}
		
		ArrayList<String> l = new ArrayList<String>();
		for(String k : highestVersions.keySet())
			l.add(k + "__v" + highestVersions.get(k));
		
		return l;
	}

	private String getCategoryAxiom(OWLClass depCat) throws OwlToSqlTransformationException 
	{
    	Set<OWLClassExpression> eces = depCat.getEquivalentClasses(activeOntology);
    	if(eces.size() > 1)
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: more than one definition of category: "+depCat);
    	else if(eces.size() == 0)
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: no definitions of category: "+depCat);

    	String r = null;
    	for(OWLClassExpression ce : eces)
    	{
    		r = renderer.render(ce);
    	}
		return r;
	}
	
	private ArrayList<String> getDependencies(String categoryName) throws SQLException, OwlToSqlTransformationException 
	{
		log.info("Chceking dependecies for: "+categoryName);
		ArrayList<String> listOfAllDependentCategories = new ArrayList<String>();
		Long id = dbTools.dbGetCategoryId(getOWLDataFactory().getOWLClass(IRI.create(categoryName)));
		if(id != null)
		{
			listOfAllDependentCategories = dbTools.dbGetDependentCategories(id);
		}
		else
			throw new OwlToSqlTransformationException("Unable to determine category id of: "+categoryName);
		
		return listOfAllDependentCategories;
		
	}

	private void writeReport() 
	{
		String reportFileSeparator = "^\t";
		File reportFile = new File(jarDirectory.concat(File.separator).concat(activeOntology.getOntologyID().getOntologyIRI().getFragment().replace(".owl", "")).concat(".rep"));
    	BufferedWriter fw = null;
		try 
		{
			fw = new BufferedWriter(new FileWriter(reportFile));
			fw.write("# OwlToSql report "+new java.util.Date());
			fw.newLine();
			fw.write("# OWL file: "+activeOntology.getOntologyID().getOntologyIRI());
			fw.newLine();
			fw.write("# Number of succesfully transformed categories: "+listOfSuccesfullyTransformedCategories.size());
			fw.newLine();
			fw.write("# Number of not transformed categories: "+listOfNotTransformedCategories.size());
			fw.newLine();
			fw.write("# List of succesfully transformed categories (name/IRI/sql/list of superclasses): ");
			fw.newLine();
			
			for(int i=0;i<listOfSuccesfullyTransformedCategories.size();i++)
			{
				OWLClass currentClass = listOfSuccesfullyTransformedCategories.get(i);
				String categoryName = currentClass.getIRI().getFragment();
				String categoryIRI = currentClass.getIRI().toString();
				String sSuperclasses = "";
				for(OWLClass cl : reasoner.getSuperClasses(currentClass, false).getFlattened())
					sSuperclasses = sSuperclasses.concat(cl.getIRI().toString()).concat(";");
				String sql = null;
				for(OWLAnnotation ann : currentClass.getAnnotations(activeOntology))
        		{
        			if(ann.getProperty().equals(sqlSelectAP))
        			{
        				if(sql==null)
        					sql = ann.getValue().toString().replace("^^xsd:string", "");
        				else
        				{
        					log.error("There is more than one SQL query for class: "+currentClass);
        					sql = "ERROR! There is more than one SQL query for this category!";
        					break;
        				}
        			}
        		}
				
				fw.write(categoryName + reportFileSeparator + categoryIRI + reportFileSeparator + sql + reportFileSeparator + sSuperclasses);
				fw.newLine();
				if(i%10000==0)
					fw.flush();
			}
			
			if(listOfNotTransformedCategories.size()>0)
			{
				fw.write("# List of not transformed categories (name/IRI): ");
				fw.newLine();
				for(int i=0;i<listOfNotTransformedCategories.size();i++)
				{
					OWLClass currentClass = listOfNotTransformedCategories.get(i);
					String categoryName = currentClass.getIRI().getFragment();
					String categoryIRI = currentClass.getIRI().toString();
					fw.write(categoryName + reportFileSeparator + categoryIRI);
					fw.newLine();
					if(i%10000==0)
						fw.flush();
				}
			}
		} 
		catch (IOException ioe)
		{
			log.error("IO Exception while preparing report file", ioe);
		} 
		finally
		{	
			if(fw != null)
				try 
				{
					fw.close();
				} 
				catch (IOException e1) 
				{
        			log.error("IO Exception while preparing report file", e1);
				}
		}
    }

//	private void transformBasicDefinition(OWLClass classToTranslate) 
//	{
//		
//	}
//	

	private Long exportCategory(OWLClass categoryToExport) throws OwlToSqlTransformationException 
	{
    	if(categoryToExport.isOWLNothing())//owl:Nothing is a subclass of every OWL class
    		throw new OwlToSqlTransformationException("Unable to transform owl:Nothing!");
    	
    	if(!checkIfClassificationCategory(categoryToExport))
			throw new OwlToSqlTransformationException("OWL class "+categoryToExport+" is not a valid classification category!");
    	
    	if(this.versionChceckingMode )
    		this.checkVersion(categoryToExport);

    	log.info("Initiating transformation of the following OWL class: "+categoryToExport);
    	
    	if(!reasoner.isSatisfiable(categoryToExport))
    	{
    		if(lfConfig.isWriteReport())
    			listOfNotTransformedCategories.add(categoryToExport);
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: unsatisfiable class: "+categoryToExport);
    	}
    	
    	Set<OWLClassExpression> eces = categoryToExport.getEquivalentClasses(activeOntology);
    	if(eces.size()>1)
    	{
    		if(lfConfig.isWriteReport())
    			listOfNotTransformedCategories.add(categoryToExport);
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: more than one definition of category: "+categoryToExport);
    	}
    	else if(eces.size()==0)
    	{
    		if(lfConfig.isWriteReport())
    			listOfNotTransformedCategories.add(categoryToExport);
    		throw new OwlToSqlTransformationException("Transformation cancelled - cause: no definition for category: "+categoryToExport);
    	}
    	
		Long newId = null;
    	for(OWLClassExpression ece : eces)
    	{
    		String basicSql;
    		Integer backwardValidity = null;
    		Integer forwardValidity = null;
    		
    		Set<OWLClass> categoriesInDefinition = ece.getClassesInSignature();
    		String expressionToTransform = renderer.render(ece);
    		if(ManchesterOWLSyntaxEditorParser.SOME.equals("koniecznie"))
    			expressionToTransform = translatePLtoENG(expressionToTransform);
    		expressionToTransform = EventRendering.transformRendering(expressionToTransform);//this makes expression available for parsing of indented temporal dependencies
    		
    		String selectClause;
    		if(expressionToTransform.contains("occurs_"))
    		{//temporal category
    			try //determine temporal validity
    			{
    					TemporalExpressionAnalyzer a = new TemporalExpressionAnalyzer(expressionToTransform);
    					backwardValidity = a.determineBackwardValidityOfAnExpresion();
    					forwardValidity = a.determineForwardValidityOfAnExpresion();
    			}
    			catch (Exception e1) 
    			{
    				if(lfConfig.isWriteReport())
    					listOfNotTransformedCategories.add(categoryToExport);
    	    		throw new OwlToSqlTransformationException("Problem during transformation of "+categoryToExport+" - unable to analyze following definition: "+ expressionToTransform, e1);
    			}
    			
    			try 
    			{
    				basicSql = temporalCategoryTransformer.transformOWLClassExpression(expressionToTransform);
        			selectClause = "SELECT pPROCESS_ID, ID ";
    				if(lfConfig.isWriteReport())
    					listOfSuccesfullyTransformedCategories.add(categoryToExport);
    			} 
    			catch (OwlToSqlTransformationException e1) 
    			{
    				if(lfConfig.isWriteReport())
    					listOfNotTransformedCategories.add(categoryToExport);
    	    		throw new OwlToSqlTransformationException("Problem during transformation of "+categoryToExport+" - unable to transform following definition: "+ expressionToTransform, e1);

    			}
    			
    			if(backwardValidity != null)
    			{
    				for(OWLAnnotationAssertionAxiom anAxiom : categoryToExport.getAnnotationAssertionAxioms(activeOntology))
    				{
    					if(anAxiom.getProperty().equals(backwardValidityAP))
    						activeOntology.getOWLOntologyManager().removeAxiom(activeOntology, anAxiom);
    				}
    				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(backwardValidityAP, getOWLDataFactory().getOWLLiteral(backwardValidity)))));
    			}
    			if(forwardValidity != null)
    			{
    				for(OWLAnnotationAssertionAxiom anAxiom : categoryToExport.getAnnotationAssertionAxioms(activeOntology))
    				{
    					if(anAxiom.getProperty().equals(forwardValidityAP))
    						activeOntology.getOWLOntologyManager().removeAxiom(activeOntology, anAxiom);
    				}
    				activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(forwardValidityAP, getOWLDataFactory().getOWLLiteral(forwardValidity)))));
    			}
    			
    		}		
    		else if((expressionToTransform.contains(" and ") || expressionToTransform.contains(" or ")) && !expressionToTransform.contains(" some ") && !expressionToTransform.contains(" value "))
    		{//compound category
    			try 
    			{
    				basicSql = compoundCategoryTransformer.transformOWLClassExpression(expressionToTransform);
    				selectClause = "SELECT DISTINCT pPROCESS_ID, EVENT_ID ";
    				if(lfConfig.isWriteReport())
    					listOfSuccesfullyTransformedCategories.add(categoryToExport);
    			} 
    			catch (OwlToSqlTransformationException e1) 
    			{
    				if(lfConfig.isWriteReport())
    					listOfNotTransformedCategories.add(categoryToExport);
    	    		throw new OwlToSqlTransformationException("Problem during transformation of "+categoryToExport+" - unable to transform following definition: "+expressionToTransform, e1);
    			}
    			
    		}
    		else
    		{
	    		throw new OwlToSqlTransformationException("Unable to transform category - unsupported definition: "+expressionToTransform);
    		}
    		
    		for(OWLAnnotationAssertionAxiom anAxiom : categoryToExport.getAnnotationAssertionAxioms(activeOntology))
    		{
    			if(anAxiom.getProperty().equals(sqlSelectAP))
    				activeOntology.getOWLOntologyManager().removeAxiom(activeOntology, anAxiom);
    		}
    		activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(sqlSelectAP, getOWLDataFactory().getOWLLiteral(basicSql)))));
    		activeOntology.getOWLOntologyManager().applyChange(new AddAxiom(activeOntology, getOWLDataFactory().getOWLAnnotationAssertionAxiom(categoryToExport.getIRI(), getOWLDataFactory().getOWLAnnotation(getOWLDataFactory().getRDFSComment(), getOWLDataFactory().getOWLLiteral("An SQL script was generated by EventsToSQLP4Transformer on "+new java.util.Date()+".")))));
    		
    		try 
    		{
				newId = Long.valueOf(this.dbTools.dbGetSequenceNextValue(lfConfig.getDbCategorySequenceName()));
				String newProcName = "P"+newId;
				String categoryType = expressionToTransform.split(" ")[0];
				Long categoryTypeId = getCategoryTypeID(categoryType, getCategoryTypeOWLClass(categoryType, ece));
				String resultsTable = getResultsTableName(categoryType);
				this.dbTools.dbCreateClassificationProcedure(newProcName, basicSql.replaceFirst("SELECT \\* ", selectClause), resultsTable);
				this.dbTools.dbAddCategory(categoryToExport, newProcName, categoryTypeId, newId, expressionToTransform);
				this.determineCategoryDependency(categoryToExport, newId, categoriesInDefinition);
				if(versionChceckingMode)
        			this.exportNewVersionsOfRelatedCategories();
			}
    		catch (Exception e) 
    		{
    			log.error("Unable to export category... ", e);
	    		throw new OwlToSqlTransformationException("Unable to export category... ", e);
    			
			}
    	}
    	return newId;
	}


	private void checkVersion(OWLClass categoryToExport) throws OwlToSqlTransformationException
	{
	// TODO implementation
		
		
	}

	private long getCategoryTypeID(String categoryType, OWLClass owlClass) throws SQLException
	{
		Long id = dbTools.dbGetCategoryTypeId(owlClass);
		if(id == null)
		{
			id = Long.valueOf(this.dbTools.dbGetSequenceNextValue(lfConfig.getDbCategoryTypeSequenceName()));
			this.dbTools.dbAddCategoryType(owlClass, id);
		}
		
		return id;
	}

	private OWLClass getCategoryTypeOWLClass(String categoryTypeIRIFragment, OWLClassExpression ece) throws OwlToSqlTransformationException 
	{
		OWLClass result = null;
		for(OWLClass c : ece.getClassesInSignature())
		{
			if(renderer.render(c).equals(categoryTypeIRIFragment))
			{
				if(result == null)
					result = c;
				else
					throw new OwlToSqlTransformationException("Duplicate OWL classes with IRI fragment: "+categoryTypeIRIFragment);
			}
		}
		return result;
	}

	private String getResultsTableName(String type) throws Exception 
	{
		String key = "DbResultsTable-"+type;
		String r = this.lfConfig.getDbConfig().getProperty(key);
		if(r == null)
			throw new Exception("Unable to determine results table for type: "+type+"; param: "+key);
		else
			return r;
	}

	private void determineCategoryDependency(OWLClass classToTranslate,	long newCategoryId, Set<OWLClass> categoriesInDefinition) throws Exception 
	{
//		Set<OWLClass> categoriesInvolved = new HashSet<OWLClass>();
		log.info(categoriesInDefinition);
		for(OWLClass category : categoriesInDefinition)
		{
//			if(categoriesInvolved.contains(category))
//			categoriesInvolved.add(category);
			
			OWLClassExpression def = null;
			Set<OWLClassExpression> eces = category.getEquivalentClasses(activeOntology);
	    	int i = 0;
	    	for(OWLClassExpression ece : eces)
	    	{
	    		i++;
	    		if(i>1)
	    			throw new OwlToSqlTransformationException("More than 1 definitions for: "+ category);
	    		
	    		def = ece;
	    	}
			
			if(def != null && checkIfClassificationCategory(category))
			{
				log.info("Analyzing: "+category);
				alreadyCheckedCombinations = new HashSet<String>();
				this.checkIfContainsCycle(classToTranslate, def);
				Long preceedingCategoryId = dbTools.dbGetCategoryId(category);
				if(preceedingCategoryId != null)
					log.info("Category "+category + " has been already exported.");
				else
				{
					log.info("Category "+category + " has to be exported because of dependency relationship.");
					preceedingCategoryId = this.exportCategory(category);
				}
				
				if(preceedingCategoryId != null)
				{
					dbTools.dbAddCategoryDependency(newCategoryId, preceedingCategoryId);
					log.info("Dependency added.");
				}
				else
					log.warn("Unable to obtain id for: "+category);
			}
		}
	}

	private boolean checkIfClassificationCategory(OWLClass category) 
	{
		if(checkIfBaseCategory(category))
			return false;
			
		for(OWLClassExpression scls : category.getSuperClasses(activeOntology))
		{
			if(!scls.isAnonymous())
			{
				if(checkIfBaseCategory(scls.asOWLClass()))
					return true;
			}
		}
		
		for(OWLClass scls : reasoner.getSuperClasses(category, false).getFlattened())
		{
			if(!scls.isAnonymous())
			{
				if(checkIfBaseCategory(scls.asOWLClass()))
					return true;
			}
		}
		
		return false;
	}
	
	private boolean checkIfBaseCategory(OWLClass category) 
	{
		return checkIfContainsAnnotation(category, baseCategoryAP, activeOntology);
	}


//	private boolean checkIfClassificationCategory(OWLClass category, OWLClassExpression def) 
//	{
//		
//		if(renderer.render(def).contains("occurs_"))
//			return true; 
//		else
//		{
//			for(OWLAnnotationAssertionAxiom anAxiom : category.getAnnotationAssertionAxioms(activeOntology))
//			{
//				if(anAxiom.getProperty().equals(baseCategoryAP))
//					return true;
//			}
//		}
//		return false;
//	}

	private void checkIfContainsCycle(OWLClass searchedCategory, OWLClassExpression def) throws OwlToSqlTransformationException 
	{
		String s = searchedCategory + ", "+renderer.render(def);
		log.info("checkIfContainsCycle: "+s);
		if(alreadyCheckedCombinations.contains(s))
		{
			log.info("Combination already checked!");
			return;
		}
		else
			alreadyCheckedCombinations.add(s);
		Set<OWLClass> categoriesInDefinition = def.getClassesInSignature();
		for(OWLClass ctFromDef : categoriesInDefinition)
		{
			if(searchedCategory.equals(ctFromDef))
    			throw new OwlToSqlTransformationException("Cycle detected in definition of "+ ctFromDef + "! Inapropriate reference to: "+searchedCategory);
			else
			{
				OWLClassExpression nextDef = null;
				Set<OWLClassExpression> eces = ctFromDef.getEquivalentClasses(activeOntology);
		    	int i = 0;
		    	for(OWLClassExpression ece : eces)
		    	{
		    		i++;
		    		if(i>1)
		    		{
		    			nextDef = null;
		    			continue;
		    		}
		    		
		    		nextDef = ece;
		    	}
		    	
		    	if(nextDef != null && checkIfClassificationCategory(ctFromDef))
		    		checkIfContainsCycle(searchedCategory, nextDef);
			}
		}	
	}

	private void initOWLObjects() throws Exception
	{
		activeOntology =  getOWLModelManager().getActiveOntology();
		sqlSelectAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#sqlSelect")));
		baseCategoryAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#baseCategory")));
		backwardValidityAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#backwardValidity")));
		forwardValidityAP = getOWLDataFactory().getOWLAnnotationProperty(IRI.create(activeOntology.getOntologyID().getOntologyIRI().toString().concat("#forwardValidity")));
		OWLReasonerManager reasonerManager = getOWLModelManager().getOWLReasonerManager();
		ReasonerUtilities.warnUserIfReasonerIsNotConfigured(getOWLWorkspace(), reasonerManager);
		if(reasonerManager.getReasonerStatus() != ReasonerStatus.INITIALIZED)
			throw new Exception("No reasoner has been initialized!");
	
        reasoner = reasonerManager.getCurrentReasoner();
        reasoner.precomputeInferences(new InferenceType[0]);
        
		dlQueryParser = new DLQueryParser(activeOntology, new SimpleShortFormProvider());

	}
	
	
	public interface LinkedFactsCategoryExportDbTools
	{
//		public void setDbConnection(Connection conn);
    	public long dbGetSequenceNextValue(String seqName) throws SQLException;
		public Long dbGetCategoryId(OWLClass cls) throws SQLException;
		public Long dbGetCategoryTypeId(OWLClass cls) throws SQLException;
		public boolean dbChceckIfCategoryAlreadyExported(OWLClass cls) throws SQLException;
		public void dbAddCategory(OWLClass categoryToExport, String newProcName, long categoryTypeId, long id, String definition) throws SQLException;
		public void dbAddCategoryType(OWLClass categoryToExport, Long id) throws SQLException;
		public void dbAddCategoryDependency(Long newCategoryId, Long preceedingCategoryId) throws SQLException;
		public void dbCreateClassificationProcedure(String newProcName, String sqlCat, String resultTable) throws SQLException;
		public void dbCommit() throws SQLException;
		public void dbRollback() throws SQLException;
		public ArrayList<String> dbGetDependentCategories(Long categoryId) throws SQLException;
		public int dbGetLastVersion(OWLClass cat) throws SQLException;

	}
	
	
	public abstract class LinkedFactsCategoryExportCommonTools implements LinkedFactsCategoryExportDbTools
	{
	    protected PreparedStatement psAddCategory;
	    protected PreparedStatement psAddCategoryType;
	    protected PreparedStatement psCheckIfAlreadyExported;
	    protected PreparedStatement psGetCategoryId;
	    protected PreparedStatement psGetCategoryTypeId;
	    protected PreparedStatement psAddDependency;
	    protected PreparedStatement psGetDependentCategories;
	    protected PreparedStatement psGetLastVersion;
		
	    protected Connection conn;

			    
		public LinkedFactsCategoryExportCommonTools(Connection conn) throws SQLException
    	{
			this.conn = conn;
    		psAddCategory = conn.prepareStatement("INSERT INTO "+lfConfig.getDbAppSchema()+".CATEGORY(IRI, NAME, PROC_NAME, TYPE_ID, ENTRY_TIME, ID, DEFINITION) VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)");
    		psAddCategoryType = conn.prepareStatement("INSERT INTO "+lfConfig.getDbAppSchema()+".CAT_TYPE(IRI, NAME, ID) VALUES (?, ?, ?)");
    		psCheckIfAlreadyExported = conn.prepareStatement("SELECT 1 FROM "+lfConfig.getDbAppSchema()+".CATEGORY WHERE NAME = ? FOR READ ONLY ");
    		psGetCategoryId = conn.prepareStatement("SELECT ID FROM "+lfConfig.getDbAppSchema()+".CATEGORY WHERE NAME = ? FOR READ ONLY ");
    		psGetCategoryTypeId = conn.prepareStatement("SELECT ID FROM "+lfConfig.getDbAppSchema()+".CAT_TYPE WHERE NAME = ? FOR READ ONLY ");
    		psAddDependency = conn.prepareStatement("INSERT INTO "+lfConfig.getDbAppSchema()+".DEPENDENCY(DEPCAT_ID, PRECAT_ID) VALUES (?, ?)");
    		psGetDependentCategories = conn.prepareStatement("SELECT C.NAME FROM "+lfConfig.getDbAppSchema()+".DEPENDENCY D JOIN "+lfConfig.getDbAppSchema()+".CATEGORY C ON C.ID=D.DEPCAT_ID WHERE PRECAT_ID = ? FOR READ ONLY ");
    		psGetLastVersion = conn.prepareStatement("SELECT C.NAME FROM "+lfConfig.getDbAppSchema()+".CATEGORY C WHERE NAME LIKE ? ORDER BY 1 DESC FOR READ ONLY ");
		}
		
		public void dbCommit() throws SQLException
		{
			log.warn("DB COMMIT");
			conn.commit();
		}

		public void dbRollback() throws SQLException
		{
			log.warn("DB ROLLBACK");
			conn.rollback();
		}
		
		@Override
		public boolean dbChceckIfCategoryAlreadyExported(OWLClass cls) throws SQLException 
		{
	    	ResultSet rs = null;
	        try 
	        {
	        	psCheckIfAlreadyExported.setString(1, cls.getIRI().getFragment());
	            rs = psCheckIfAlreadyExported.executeQuery();
	            
	            log.info("dbChceckIfCategoryAlreadyExported: "+ cls.getIRI().getFragment());
	        	return rs.next();
	            
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	        }
		}
		
    	public Long dbGetCategoryId(OWLClass cls) throws SQLException
    	{
	    	ResultSet rs = null;
	        try 
	        {
	        	psGetCategoryId.setString(1, cls.getIRI().getFragment());
	            rs = psGetCategoryId.executeQuery();
	            
	            log.info("psGetCategoryId: "+ cls.getIRI().getFragment());
	        	if(rs.next())
	        		return rs.getLong(1);
	        	else
	        		return null;
	            
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	        }
		}
    	
    	public Long dbGetCategoryTypeId(OWLClass cls) throws SQLException
    	{
    		ResultSet rs = null;
    		try 
    		{
    			psGetCategoryTypeId.setString(1, cls.getIRI().getFragment());
    			rs = psGetCategoryTypeId.executeQuery();
    			
    			log.info("psGetCategoryTypeId: "+ cls.getIRI().getFragment());
    			if(rs.next())
    				return rs.getLong(1);
    			else
    				return null;
    			
    		} 
    		catch (SQLException e) 
    		{
    			e.printStackTrace();
    			log.error(e);
    			throw e;
    		}
    		finally 
    		{
    			if(rs!=null)
    				rs.close();
    		}
    	}
		


		@Override
		public void dbAddCategory(OWLClass categoryToExport, String newProcName, long categoryTypeId, long id, String definition) throws SQLException 
		{
	        try 
	        {
	        	psAddCategory.setString(1, categoryToExport.getIRI().toString());
	        	psAddCategory.setString(2, categoryToExport.getIRI().getFragment());
	        	psAddCategory.setString(3, newProcName);
	        	psAddCategory.setLong(4, categoryTypeId);
	        	psAddCategory.setLong(5, id);
	        	psAddCategory.setString(6, definition);
	        	
	        	psAddCategory.execute();
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
		}
		
		@Override
		public void dbAddCategoryType(OWLClass categoryToExport, Long id) throws SQLException 
		{
			try 
			{
				psAddCategoryType.setString(1, categoryToExport.getIRI().toString());
				psAddCategoryType.setString(2, categoryToExport.getIRI().getFragment());
				psAddCategoryType.setLong(3, id);

				
				psAddCategoryType.execute();
			} 
			catch (SQLException e) 
			{
				e.printStackTrace();
				log.error(e);
				throw e;
			}
		}
		
		public void dbAddCategoryDependency(Long newCategoryId, Long preceedingCategoryId) throws SQLException
		{
			try 
	        {
	        	psAddDependency.setLong(1, newCategoryId);
	        	psAddDependency.setLong(2, preceedingCategoryId);
	        	
	        	psAddDependency.execute();
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
		}
		
		public ArrayList<String> dbGetDependentCategories(Long categoryId) throws SQLException
		{
			ResultSet rs = null;
			ArrayList<String> l = new ArrayList<String>();
	        try 
	        {
	        	log.info("psGetDependentCategories: "+ categoryId);
	        	psGetDependentCategories.setLong(1, categoryId);
	            rs = psGetDependentCategories.executeQuery();
	            
				while (rs.next())
	        		l.add(rs.getString(1));
				
				return l;
	            
	        } 
	        catch (SQLException e) 
	        {
	        	e.printStackTrace();
	            log.error(e);
	            throw e;
	        }
	        finally 
	        {
	            if(rs!=null)
	            	rs.close();
	        }
		}
		
		public int dbGetLastVersion(OWLClass cls) throws SQLException
		{
	 		ResultSet rs = null;
    		try 
    		{
    			log.info(cls.getIRI().getFragment().substring(0, cls.getIRI().getFragment().lastIndexOf("__v")+3).concat("%"));
    			psGetLastVersion.setString(1, cls.getIRI().getFragment().substring(0, cls.getIRI().getFragment().lastIndexOf("__v")+3).concat("%"));
    			rs = psGetLastVersion.executeQuery();
    			
    			log.info("psGetLastVersion: "+ cls.getIRI().getFragment());
    			if(rs.next())
    			{
    				String s = rs.getString(1);
    				if(s.contains("__v")) 
    				{
    					int v = Integer.parseInt(s.substring(s.lastIndexOf("__v")+3));
    					log.info(v);
    					return v;
    				}
    				else
    					return -1;
    			}
    			else
    				return -1;
    			
    		} 
    		catch (SQLException e) 
    		{
    			e.printStackTrace();
    			log.error(e);
    			throw e;
    		}
    		finally 
    		{
    			if(rs!=null)
    				rs.close();
    		}
		}


	}
	
	public class LinkedFactsCategoryExportDB2Tools extends LinkedFactsCategoryExportCommonTools
	{
		
		public LinkedFactsCategoryExportDB2Tools(Connection conn) throws SQLException
		{
			super(conn);
		}
		
		@Override
		public long dbGetSequenceNextValue(String seqName) throws SQLException 
		{
			Statement s = null;
			ResultSet rs = null;
			try
			{
				String sql = "SELECT NEXT VALUE FOR "+lfConfig.getDbAppSchema()+"."+seqName+" AS NEXTID FROM SQLTOOLS.DUAL FOR FETCH ONLY";
				log.info(sql);
				s = conn.createStatement();
				rs = s.executeQuery(sql);
				if(rs.next())
					return rs.getLong(1);
				else
					throw new SQLException("Unable to use sequence "+seqName);
				
			}
			catch (SQLException e)
			{
				e.printStackTrace();
				log.error(e);
				throw e;
			}
		}
		

		@Override
		public void dbCreateClassificationProcedure(String newProcName, String sqlCat, String resultTable) throws SQLException 
		{
			Statement s = null;
			StringBuffer sb = new StringBuffer();
			sb.append("CREATE PROCEDURE "+lfConfig.getDbAppSchema()+"."+newProcName+" "); 
			sb.append("( IN pPROCESS_ID INT) "); 
			sb.append("LANGUAGE SQL "); 
			sb.append("MODIFIES SQL DATA "); 
			sb.append("CALLED ON NULL INPUT SET OPTION ALWBLK = *ALLREAD , ALWCPYDTA = *OPTIMIZE , COMMIT = *NONE "); //*NONE has to be stated here in beacause *CHG is the default
			sb.append("BEGIN "); 
			sb.append("DECLARE vRESULTS_COUNT INT; "); 
			sb.append("DECLARE vPROCESS_COUNT INT; "); 
			sb.append("SELECT COUNT(*) INTO vPROCESS_COUNT FROM "+lfConfig.getDbAppSchema()+".PROCESS WHERE START_TIME IS NOT NULL AND ID = pPROCESS_ID; "); 
			sb.append("IF vPROCESS_COUNT = 0 THEN "); 
				sb.append("UPDATE "+lfConfig.getDbAppSchema()+".PROCESS SET STATUS = 1, START_TIME = CURRENT_TIMESTAMP WHERE ID = pPROCESS_ID; "); 
				sb.append("INSERT INTO "+lfConfig.getDbAppSchema()+"."+resultTable+" "); 
				sb.append(sqlCat + "; "); 
				sb.append("GET DIAGNOSTICS vRESULTS_COUNT = ROW_COUNT; ");
				sb.append("UPDATE "+lfConfig.getDbAppSchema()+".PROCESS SET STATUS = 2, RESULTS_COUNT = vRESULTS_COUNT, END_TIME = CURRENT_TIMESTAMP WHERE ID = pPROCESS_ID; "); 
			sb.append("END IF; ");
			sb.append("END ");
			String sql = sb.toString();
			log.info(sql);
			try {
				s = conn.createStatement();
				s.executeUpdate(sql);
			} catch (SQLException e) {
				e.printStackTrace();
				log.error(e);
				throw e;
			}
			
		}
		


//		@Override
//		public void dbCreateClassificationProcedure(String newProcName, String sqlCat, String resultTable, String categoryColumn) throws SQLException 
//		{
//			Statement s = null;
//			StringBuffer sb = new StringBuffer();
//			sb.append("CREATE PROCEDURE "+lfConfig.getDbAppSchema()+"."+newProcName+" "); 
//			sb.append("( IN pPROCESS_ID INT) "); 
//			sb.append("LANGUAGE SQL "); 
//			sb.append("MODIFIES SQL DATA "); 
//			sb.append("BEGIN "); 
//			sb.append("DECLARE vRESULTS_COUNT INT; "); 
//			sb.append("UPDATE "+lfConfig.getDbAppSchema()+".PROCESS SET STATUS = 1, START_TIME = CURRENT_TIMESTAMP WHERE ID = pPROCESS_ID; "); 
//			sb.append("UPDATE "+lfConfig.getDbAppSchema()+"."+resultTable+" SET "+categoryColumn+" = pPROCESS_ID WHERE ID IN ( "); 
//			sb.append(sqlCat.substring(1, sqlCat.length()-1).replaceFirst("SELECT \\* ", "SELECT S1L1.ID ")+" ); "); //ommiting double quotes
//			sb.append("GET DIAGNOSTICS vRESULTS_COUNT = ROW_COUNT; "); 
//			sb.append("UPDATE "+lfConfig.getDbAppSchema()+".PROCESS SET STATUS = 2, RESULTS_COUNT = vRESULTS_COUNT, END_TIME = CURRENT_TIMESTAMP WHERE ID = pPROCESS_ID; "); 
//			sb.append("END ");
//			String sql = sb.toString();
//			log.info(sql);
//			try {
//				s = conn.createStatement();
//				s.executeUpdate(sql);
//			} catch (SQLException e) {
//				e.printStackTrace();
//				log.error(e);
//				throw e;
//			}
//			
//		}

	}
	
	/*
	 * Some common methods. Consider moving them to a separate tools class.
	 * 
	 */
	private static String showPasswordPanel(String message)
	{
		JPasswordField pf = new JPasswordField();
		int okCxl = JOptionPane.showConfirmDialog(null, pf, message, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
		
		if (okCxl == JOptionPane.OK_OPTION) 
			return new String(pf.getPassword());
		else if (okCxl == JOptionPane.CANCEL_OPTION) 
			return null;
		else
			return null;
	}
	
	protected static String[] showDatabeseSignOnPanel(String defaultUser)
	{
		String dbUser = null;
		String dbPasswd = null;
		JPanel p = new JPanel();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
		JTextField uf = new JTextField(defaultUser);
		JPasswordField pf = new JPasswordField();
		JLabel ufl = new JLabel("User:");
		JLabel pfl = new JLabel("Password:");
		ufl.setFont(new Font(ufl.getFont().getFontName(), Font.BOLD, ufl.getFont().getSize()));
		pfl.setFont(new Font(pfl.getFont().getFontName(), Font.BOLD, pfl.getFont().getSize()));
		p.add(ufl);
		p.add(uf);
		p.add(pfl);
		p.add(pf);
	
    	int okCxl = JOptionPane.showConfirmDialog(null, p, "Database sign on", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);

    	if (okCxl == JOptionPane.OK_OPTION) 
    	{
    	  dbPasswd = new String(pf.getPassword());
    	  dbUser = new String(uf.getText());
    	}
//    	else if (okCxl == JOptionPane.CANCEL_OPTION) 
//    	{
//    		dbPasswd = null;
//    	}
    	
    	return new String[]{dbUser, dbPasswd};
	}
	
	private static Connection getUserProvidedConnection(String connURL, String driverName, String user, String passwd) throws Exception
    {
    	Connection result = null;
    	try 
    	{
    		Class.forName(driverName).newInstance();
    	}
    	catch (Exception e)
    	{
    		System.out.println("Check classpath. Cannot load db driver: " + driverName);
    		e.printStackTrace();
    		throw e;
    	}
    	
    	try
    	{
    		result = DriverManager.getConnection(connURL, user, passwd);
    	}
    	catch (SQLException e)
    	{
    		System.out.println("Driver loaded, but cannot connect to db: " + connURL);
    		e.printStackTrace();
    		throw e;
    		
    	}
    	return result;
    }
	
	private static String translatePLtoENG(String expressionToTransform)
	{
		Matcher m = TextProcessingUtils.plIPattern.matcher(expressionToTransform);//i -> and
		if(m.find())
			expressionToTransform = m.replaceAll(" and ");
		m = TextProcessingUtils.plLUBPattern.matcher(expressionToTransform);//lub -> or
		if(m.find())
			expressionToTransform = m.replaceAll(" or ");
		m = TextProcessingUtils.plKONIECZNIE1Pattern.matcher(expressionToTransform);//koniecznie -> some
		if(m.find())
			expressionToTransform = m.replaceAll(" some ");
		
		m = TextProcessingUtils.plNIEPattern.matcher(expressionToTransform);//nie ( -> not (
		if(m.find())
			expressionToTransform = m.replaceAll(" not (");
		do
		{
			m = TextProcessingUtils.plNIEPattern2.matcher(expressionToTransform);//(nie ( -> not (
			if(m.find())
				expressionToTransform = m.replaceFirst(" ".concat(m.group(1)).concat("not ("));
			m = TextProcessingUtils.plNIEPattern2.matcher(expressionToTransform);//(nie ( -> not (
		}
		while(m.find());
		
		return expressionToTransform;
	}

	private static boolean checkIfContainsAnnotation(OWLClass category, OWLAnnotationProperty annotationProperty, OWLOntology ont) 
	{
		for(OWLAnnotationAssertionAxiom anAxiom : category.getAnnotationAssertionAxioms(ont))
		{
			if(anAxiom.getProperty().equals(annotationProperty))
				return true;
		}
		return false;
	}

}
